package com.kehutong.charge.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.kehutong.charge.entity.*;
import com.kehutong.common.util.BigDecimalUtils;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.util.time.TimeUtil;
import com.kehutong.charge.service.ChargeUrgingService;
import com.kehutong.charge.service.CommonService;
import com.kehutong.charge.service.ThirdPayManageService;
import com.kehutong.charge.util.CommonClient;
import com.kehutong.charge.util.enums.ChargeBillStatusEnum;
import com.kehutong.charge.util.enums.ChargeLogEnum;
import com.kehutong.charge.util.enums.ChargeOrderStatusEnum;
import com.kehutong.charge.util.enums.CommonEnum;
import com.kehutong.common.DoveClient;
import com.kehutong.common.Java8TimeUtils;
import com.kehutong.common.dto.UniformSendReqDto;
import com.kehutong.common.enums.MessageBusinessEnum;
import com.kehutong.common.enums.TemplateType;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.urlconfig.WebUrlConfig;
import com.kehutong.common.util.BigDecimalUtils;
import com.kehutong.common.util.TemplateReplaceUtil;
import com.kehutong.common.util.Token;

/**
 * @author joneRon
 * @Title: kht
 * @Description: 第三方支付管理
 * @date 2021/7/30
 */
@WebService("/charge/pay/service")
public class ThirdPayManageServiceImpl implements ThirdPayManageService {

    private static final Logger logger = LoggerFactory.getLogger(ThirdPayManageServiceImpl.class);

    private static final String SUCCESS = "SUCCESS";

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private DoveClient doveClient;
    @Inject
    private WebUrlConfig webUrlConfig;
    @Inject
    private CommonService commonService;
    @Inject
    CommonClient commonClient;
    @Inject
    private ChargeUrgingService chargeUrgingService;




    @Override
    @ReqMapping("/order/callPay")
    public Object callPayOrder(ChargePayManage cpm, JSONObject jsonObject, Token token) throws Exception {

        String payMethod = cpm.getPayMethod().getId();

        if(Objects.isNull(payMethod)){
            return Result.error(123,"支付或来源有问题！");
        }

        //2、选择支付方式（现金、微信、支付宝、银行卡）
        switch (CommonEnum.getById(payMethod)) {
            case COM_PAY_CASH: //现金收款
                return callPay(jsonObject,token);
            case COM_PAY_WXPAY_MP:  // 微信支付
                return callWeChatPay(cpm,jsonObject);
            case COM_PAY_WXPAY_WEB: //web 扫码支付
                return callWeChatPay(cpm,jsonObject);
            default:
                return Result.error(123,"支付或来源有问题");
        }
    }






    /**
     * 现金支付
     * @param jsonObject
     * @return
     */
    private Object callPay(JSONObject jsonObject,Token token){

        String orderOrigin = jsonObject.getString("orderOrigin");
        if(Objects.isNull(orderOrigin)){
            return Result.error(123,"支付或来源有问题！");
        }

        // 订单临时入口和常规入口
        if(CommonEnum.COM_PAY_ROUTINE.getId().equals(orderOrigin)){
            return callCashPay(jsonObject,token);
        }else if (CommonEnum.COM_PAY_INTERIM.getId().equals(orderOrigin)){
            return callInterimCashPay(jsonObject,token);
        }

        return Result.success();
    }

    /**
     * 回调处理
     * @param jsonObject
     * @return
     */
    // todo
//        jsonObject = {JSONObject@6037}  size = 22
//        "transaction_id" -> "4200001149202108223123933284"
//        "nonce_str" -> "6001454044579510270"
//        "bank_type" -> "OTHERS"
//        "openid" -> "oHr394tgZXj_ePgirDZ0lCstdzKE"
//        "sign" -> ""
//        "sub_is_subscribe" -> "N"
//        "fee_type" -> "CNY"
//        "mch_id" -> "1604371984"
//        "sub_appid" -> "wx3f14689148e657a2"
//        "sub_mch_id" -> "1604438984"
//        "cash_fee" -> "1"
//        "sub_openid" -> "oHr394tgZXj_ePgirDZ0lCstdzKE"
//        "token" -> {Token@6092} "token:[sessionId=null, companyNo=162159317073429801, companyName=null, suiteId=null, uuid=null, remindTime=null, settingState=false, businessState=false, frontPageState=false, newsletterState=false, userId=null, username=null]"
//        "subOrderNo" -> "162962608553610040"
//        "out_trade_no" -> "210822175445750103"
//        "appid" -> "wx3f14689148e657a2"
//        "total_fee" -> "1"
//        "trade_type" -> "NATIVE"
//        "result_code" -> "SUCCESS"
//        "time_end" -> "20210822175458"
//        "is_subscribe" -> "N"
//        "return_code" -> "SUCCESS"
    @Override
    @ReqMapping("/order/callback")
    public Object callbackPayOrder(JSONObject jsonObject) {

        logger.info("*****************支付回调处理接口************************"+jsonObject);

        /**
         * 保存回调数据
         */
        String subOrderNo = jsonObject.getString("subOrderNo");
        ChargePayManage entity = Pool.get(ChargePayManage.class, subOrderNo);
        String transactionId = jsonObject.getString("transaction_id");
        entity.setTransactionId(transactionId);
        entity.setBankType(jsonObject.getString("transaction_id"));
        entity.setOpenId(jsonObject.getString("openid"));
        entity.setMchId(jsonObject.getString("mch_id"));
        entity.setSubMchId(jsonObject.getString("sub_mch_id"));
        String orderNoThird = jsonObject.getString("out_trade_no");

        /**
         * 处理状态
         */
        JSONObject jsonObj = JSONObject.parseObject(jsonObject.getString("attach"), JSONObject.class);
        String orderOrigin = jsonObj.getString("orderOrigin");
        String orderNo = jsonObj.getString("orderNo");
        String userNo = jsonObj.getString("userNo");

        logger.info("*****支付回调处理状态：**********"+jsonObj);

        if(Objects.equals(jsonObject.getString("return_code"), SUCCESS)
                && Objects.equals(jsonObject.getString("result_code"), SUCCESS)){

            entity.setStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
            // 订单临时入口和常规入口
            if(CommonEnum.COM_PAY_ROUTINE.getId().equals(orderOrigin)){
                //批次数据
                List<ChargeOrderManage> orderManageList = jdbcSession.findArray(ChargeOrderManage.class)
                        .eq("batchOrderNo",orderNo).exe();
                for (int i = 0; i < orderManageList.size(); i++) {
                    ChargeOrderManage orderManage = orderManageList.get(i);
                    orderManage.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
                    orderManage.setOptStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
                    orderManage.setFinishTime(TimeUtil.timestamp());
                    orderManage.setPayTime(TimeUtil.timestamp());
                    orderManage.setOrderNoThird(orderNoThird);
                    orderManage.setPaymentAmount(orderManage.getPayableAmount());
                    orderManage.setPayableAmount(BigDecimal.ZERO);
                    orderManage.setTransactionId(transactionId);
                    orderManage.setMchName(entity.getMchName());
                    orderManage.setPayMethod(CommonEnum.COM_PAY_WECHAT);

                    jdbcSession.updateById(orderManage);

                    //更新账单状态
                    updateData(orderManage,true,entity.getCompanyNo());

                    //修改违约金
                    List<ChargePenaltyOrder> penaltyOrders = jdbcSession.findArray(ChargePenaltyOrder.class)
                            .eq("penaltyOrderNo",orderManage.getOrderNo()).exe();
                    for (int b = 0; b < penaltyOrders.size(); b++) {
                        ChargePenaltyOrder penaltyOrder = penaltyOrders.get(b);
                        penaltyOrder.setBillStatus(ChargeBillStatusEnum.BILL_PAID);
                        penaltyOrder.setModifyTime(TimeUtil.timestamp());
                        jdbcSession.updateById(penaltyOrder);
                    }
                }

                /**
                 * 成功之后调用消息
                 */
                // todo: 调用消息
                try{

                    logger.info("支付回调处理发送消息：用户：{},订单：{},公司编号：{}",userNo,orderNo,entity.getCompanyNo());

                    //根据用户查询手机号码
                    JSONObject object = commonClient.findResidentInfo(userNo);

                    ChargeOrderManage manage = jdbcSession.findOne(ChargeOrderManage.class)
                            .eq("batchOrderNo",orderNo)
                            .eq("orderStatus",ChargeOrderStatusEnum.ORDER_PAY_SUCCESS).exe();
                    List<String> phoneList = new ArrayList<>();
                    phoneList.add(object.getString("mobile")); //手机号
                    //manage.setChargeName(object.getString("realname"));
                    msgUniformSend(manage,userNo,TemplateType.PAY_C_BILL_SUCCESS, phoneList,true, entity.getCompanyNo());

                }catch (Exception e){
                    logger.error("缴费消息推送异常"+e.getMessage(), e);
                }

            }else if (CommonEnum.COM_PAY_INTERIM.getId().equals(orderOrigin)){

                //1、修改账单状态
                ChargeOrderInterim itemsList = jdbcSession.findOne(ChargeOrderInterim.class)
                        .eq("interimOrderNo",orderNo).exe();
                itemsList.setOrderNoThird(orderNoThird);
                itemsList.setTransactionId(transactionId);
                itemsList.setMchName(entity.getMchName());

                updateDataInterim(itemsList);

                /**
                 * 成功之后调用消息
                 */
                // todo: 调用消息
                try{
                    //根据用户查询手机号码
                    JSONObject object = commonClient.findResidentInfo(userNo);

                    ChargeOrderManage manage = jdbcSession.findOne(ChargeOrderManage.class)
                            .eq("orderNo",orderNo)
                            .eq("orderStatus",ChargeOrderStatusEnum.ORDER_PAY_SUCCESS).exe();
                    List<String> phoneList = new ArrayList<>();
                    phoneList.add(object.getString("mobile")); //手机号
                    //manage.setChargeName(object.getString("realname"));
                    msgUniformSend(manage,userNo,TemplateType.PAY_C_BILL_SUCCESS, phoneList,true, entity.getCompanyNo());

                }catch (Exception e){
                    logger.error("缴费消息推送异常"+e.getMessage(), e);
                }
            }
        }else{
            entity.setStatus(ChargeOrderStatusEnum.ORDER_PAY_FAIL);
            logger.error("回调说明：订单：{}，失败！",orderNo);
        }

        jdbcSession.updateById(entity);

        return Result.success();
    }

    /**
     * 发送消息
     * @param manage 模板替换内容对象
     * @param uuid 用户ID
     * @param templateType  模板CODE
     * @param phoneList 手机号
     * @param userCreate 是否小程序用户，false 员工，true 小程序用户
     * @throws Exception
     */
    private void msgUniformSend2(ChargeOrderManage manage, String uuid, TemplateType templateType, List<String> phoneList, boolean userCreate, String companyNo) throws Exception {
        // 获取消息推送配置文件
        JSONObject configJson = doveClient.post("/crm/message/global/config/service/get", (http) -> {
            http.addParam("templateType", templateType.getId());
        });

        if (configJson.getIntValue("code") == 200) {
            UniformSendReqDto dto = getUniformSendReqDto2(manage, uuid, templateType, phoneList, configJson.getJSONObject("data"), userCreate, companyNo);
            // 消息推送
            doveClient.post("/crm/message/service/uniformSend", (http) -> {
                http.addParam("temp", JSONObject.toJSONString(dto));
            });
        }
    }

    private UniformSendReqDto getUniformSendReqDto2(ChargeOrderManage manage, String uuid, TemplateType templateType,
                                                   List<String> phoneList, JSONObject dataJson, boolean userCreate,
                                                   String companyNo) throws Exception {
        UniformSendReqDto dto = new UniformSendReqDto();
        dto.setMsgId(manage.getId());
        dto.setBusinessTypeId(MessageBusinessEnum.MSG_BILL_PAY.getId());
        dto.setTemplateTypeId(templateType.getId());
        dto.setCompanyNo(companyNo);
        dto.setUserCreate(userCreate);
        dto.setUuid(uuid);
        dto.setTitle("缴费完成");

        String param = "type=3&orderNo="+manage.getOrderNo();

        JSONObject inner = dataJson.getJSONObject("messageTemplateInner");
        if (dataJson.getBooleanValue("innerSend") && org.coraframework.util.Objects.nonNull(inner)) {
            dto.setTitle(inner.getString("title"));
            dto.setInnerData(TemplateReplaceUtil.replace(inner.getString("content"), inner.getString("tagArray"), manage));
            dto.setPageParam(param);
        }

        JSONObject app = dataJson.getJSONObject("messageTemplateApp");
        if (dataJson.getBooleanValue("appSend") && org.coraframework.util.Objects.nonNull(app)) {
            dto.setTitle(app.getString("title"));
            dto.setAppData(TemplateReplaceUtil.replace(app.getString("content"), app.getString("tagArray"), manage));
            dto.setAppToUrl(webUrlConfig.getUrl("/web-app/?page=fees-details/index?" + URLEncoder.encode(param, "UTF-8")));
        }

        JSONObject sms = dataJson.getJSONObject("messageTemplateSms");
        if (dataJson.getBooleanValue("smsSend") && org.coraframework.util.Objects.nonNull(sms)) {
            if (org.coraframework.util.Objects.nonEmpty(phoneList)){
                dto.setPhoneList(phoneList);
                dto.setSmsDataParams(TemplateReplaceUtil.listTencentSmsParam(sms.getString("content"), sms.getString("tagArray"), manage));
            } else {
                // 去员工表取手机号
                JSONObject jsonObject = doveClient.post("/kht-bin/auth/user/listPhone", http -> {
                    JSONObject temp = new JSONObject();
                    temp.put("id", Arrays.asList(uuid));
                    http.setBody(temp.toJSONString());
                });
                List<String> listPhone = JSONArray.parseArray(jsonObject.getString("data"), String.class);
                if (org.coraframework.util.Objects.nonEmpty(listPhone)){
                    dto.setPhoneList(listPhone);
                    dto.setSmsDataParams(TemplateReplaceUtil.listTencentSmsParam(sms.getString("content"), sms.getString("tagArray"), manage));
                }
            }

        }

        String wxchatTemplate = dataJson.getString("wxchatTemplate");
        if (dataJson.getBooleanValue("wxchatSend") && org.coraframework.util.Objects.nonNull(wxchatTemplate)) {
            if (TemplateType.PAY_C_BILL_SUCCESS == templateType) {
                dto.setWxChatData(getWxchatTemplate2(templateType, manage));
                dto.setPageParam(String.format("yearMonth=%s&houseBillNo=%s&houseNo=%s&companyNo=%s",
                        manage.getOrderYearMonth(),manage.getHouseBillNo(),manage.getHouseNo(),companyNo));
            } else if (TemplateType.PAY_B_TASK_SUCCESS_REMIND == templateType) {
                dto.setWxChatData(getWxchatTemplate2(templateType, manage));
                dto.setPageParam(String.format("type=3&orderNo=%s", manage.getOrderNo()));
            } else {
                // continue
            }
        }

        return dto;
    }

    private String getWxchatTemplate2(TemplateType templateType, ChargeOrderManage manage){
        JSONObject data = new JSONObject();

        if(TemplateType.PAY_C_BILL_SUCCESS == templateType){
            data.put("first", buildMpMessageData("您的缴费已收到"));
            // 缴费地址
            data.put("keyword1", buildMpMessageData(manage.getBillAddress()));
            // 交易单号
            data.put("keyword2", buildMpMessageData(manage.getOrderNoThird()));
            // 支付金额
            data.put("keyword3", buildMpMessageData(BigDecimalUtils.format(manage.getPaymentAmount()).toPlainString()));
            // 支付方式
            data.put("keyword4", buildMpMessageData(manage.getPayMethod().getDesc()));
            // 支付时间
            data.put("keyword5", buildMpMessageData(Java8TimeUtils.parseString(manage.getPayTime().toLocalDateTime())));

            data.put("remark", buildMpMessageData("感谢您的支持与关注！"));
            return data.toJSONString();
        } else if (TemplateType.PAY_B_TASK_SUCCESS_REMIND == templateType) {
            data.put("first", buildMpMessageData("有住户完成缴费"));
            // 小区名称
            data.put("keyword1", buildMpMessageData(manage.getCommunityName()));
            // 业主信息
            data.put("keyword2", buildMpMessageData(manage.getBillAddress() +":"+manage.getChargeName()));
            // 缴费金额
            data.put("keyword3", buildMpMessageData(BigDecimalUtils.format(manage.getPaymentAmount()).toPlainString()));
            // 缴费类型
            data.put("keyword4", buildMpMessageData(manage.getPayMethod().getDesc()));
            // 缴费时间
            data.put("keyword5", buildMpMessageData(Java8TimeUtils.parseString(manage.getPayTime().toLocalDateTime())));

            data.put("remark", buildMpMessageData("仅供参考。"));
            return data.toJSONString();
        } else {
            return null;
        }
    }

    /**
     * 发送消息
     * @param manage 模板替换内容对象
     * @param uuid 用户ID
     * @param templateType  模板CODE
     * @param phoneList 手机号
     * @param userCreate 是否小程序用户，false 员工，true 小程序用户
     * @throws Exception
     */
    private void msgUniformSend(ChargeOrderManage manage, String uuid, TemplateType templateType, List<String> phoneList, boolean userCreate, String companyNo) throws Exception {
        // 获取消息推送配置文件
        JSONObject configJson = doveClient.post("/crm/message/global/config/service/get", (http) -> {
            http.addParam("templateType", templateType.getId());
        });

        if (configJson.getIntValue("code") == 200) {
            UniformSendReqDto dto = getUniformSendReqDto(manage, uuid, templateType, phoneList, configJson.getJSONObject("data"), userCreate, companyNo);
            // 消息推送
            doveClient.post("/crm/message/service/uniformSend", (http) -> {
                http.addParam("temp", JSONObject.toJSONString(dto));
            });
        }
    }

    private UniformSendReqDto getUniformSendReqDto(ChargeOrderManage manage, String uuid, TemplateType templateType,
                                                   List<String> phoneList, JSONObject dataJson, boolean userCreate,
                                                   String companyNo) throws Exception {
        UniformSendReqDto dto = new UniformSendReqDto();
        dto.setMsgId(manage.getId());
        dto.setBusinessTypeId(MessageBusinessEnum.MSG_BILL_PAY.getId());
        dto.setTemplateTypeId(templateType.getId());
        dto.setCompanyNo(companyNo);
        dto.setUserCreate(userCreate);
        dto.setUuid(uuid);
        dto.setTitle("缴费完成");

        String param = "type=3&orderNo="+manage.getOrderNo();

        JSONObject inner = dataJson.getJSONObject("messageTemplateInner");
        if (dataJson.getBooleanValue("innerSend") && org.coraframework.util.Objects.nonNull(inner)) {
            dto.setTitle(inner.getString("title"));
            dto.setInnerData(TemplateReplaceUtil.replace(inner.getString("content"), inner.getString("tagArray"), manage));
            dto.setPageParam(param);
        }

        JSONObject app = dataJson.getJSONObject("messageTemplateApp");
        if (dataJson.getBooleanValue("appSend") && org.coraframework.util.Objects.nonNull(app)) {
            dto.setTitle(app.getString("title"));
            dto.setAppData(TemplateReplaceUtil.replace(app.getString("content"), app.getString("tagArray"), manage));
            dto.setAppToUrl(webUrlConfig.getUrl("/web-app/?page=fees-details/index?" + URLEncoder.encode(param, "UTF-8")));
        }

        JSONObject sms = dataJson.getJSONObject("messageTemplateSms");
        if (dataJson.getBooleanValue("smsSend") && org.coraframework.util.Objects.nonNull(sms)) {
            if (org.coraframework.util.Objects.nonEmpty(phoneList)){
                dto.setPhoneList(phoneList);
                dto.setSmsDataParams(TemplateReplaceUtil.listTencentSmsParam(sms.getString("content"), sms.getString("tagArray"), manage));
            } else {
                // 去员工表取手机号
                JSONObject jsonObject = doveClient.post("/kht-bin/auth/user/listPhone", http -> {
                    JSONObject temp = new JSONObject();
                    temp.put("id", Arrays.asList(uuid));
                    http.setBody(temp.toJSONString());
                });
                List<String> listPhone = JSONArray.parseArray(jsonObject.getString("data"), String.class);
                if (org.coraframework.util.Objects.nonEmpty(listPhone)){
                    dto.setPhoneList(listPhone);
                    dto.setSmsDataParams(TemplateReplaceUtil.listTencentSmsParam(sms.getString("content"), sms.getString("tagArray"), manage));
                }
            }

        }

        String wxchatTemplate = dataJson.getString("wxchatTemplate");
        if (dataJson.getBooleanValue("wxchatSend") && org.coraframework.util.Objects.nonNull(wxchatTemplate)) {
            if (TemplateType.PAY_C_BILL_SUCCESS == templateType) {
                dto.setWxChatData(getWxchatTemplate(templateType, manage));
                dto.setPageParam(String.format("yearMonth=%s&houseBillNo=%s&houseNo=%s&companyNo=%s",
                        manage.getOrderYearMonth(),manage.getHouseBillNo(),manage.getHouseNo(),companyNo));
            } else if (TemplateType.PAY_B_TASK_SUCCESS_REMIND == templateType) {
                dto.setWxChatData(getWxchatTemplate(templateType, manage));
                dto.setPageParam(String.format("type=3&orderNo=%s", manage.getOrderNo()));
            } else {
                // continue
            }
        }

        return dto;
    }

    private String getWxchatTemplate(TemplateType templateType, ChargeOrderManage manage){
        JSONObject data = new JSONObject();

        if(TemplateType.PAY_C_BILL_SUCCESS == templateType){
            data.put("first", buildMpMessageData("您的缴费已收到"));
            // 缴费地址
            data.put("keyword1", buildMpMessageData(manage.getBillAddress()));
            // 交易单号
            data.put("keyword2", buildMpMessageData(manage.getOrderNoThird()));
            // 支付金额
            data.put("keyword3", buildMpMessageData(BigDecimalUtils.format(manage.getPaymentAmount()).toPlainString()));
            // 支付方式
            data.put("keyword4", buildMpMessageData(manage.getPayMethod().getDesc()));
            // 支付时间
            data.put("keyword5", buildMpMessageData(Java8TimeUtils.parseString(manage.getPayTime().toLocalDateTime())));

            data.put("remark", buildMpMessageData("感谢您的支持与关注！"));
            return data.toJSONString();
        } else if (TemplateType.PAY_B_TASK_SUCCESS_REMIND == templateType) {
            data.put("first", buildMpMessageData("有住户完成缴费"));
            // 小区名称
            data.put("keyword1", buildMpMessageData(manage.getCommunityName()));
            // 业主信息
            data.put("keyword2", buildMpMessageData(manage.getBillAddress() +":"+manage.getChargeName()));
            // 缴费金额
            data.put("keyword3", buildMpMessageData(BigDecimalUtils.format(manage.getPaymentAmount()).toPlainString()));
            // 缴费类型
            data.put("keyword4", buildMpMessageData(manage.getPayMethod().getDesc()));
            // 缴费时间
            data.put("keyword5", buildMpMessageData(Java8TimeUtils.parseString(manage.getPayTime().toLocalDateTime())));

            data.put("remark", buildMpMessageData("仅供参考。"));
            return data.toJSONString();
        } else {
            return null;
        }
    }

    private JSONObject buildMpMessageData(String value) {
        JSONObject json = new JSONObject();
        json.put("value", value);
        return json;
    }


    /**
     * 退款处理
     * @param jsonObject
     * @return
     */
    @Override
    @ReqMapping("/order/reFund")
    public Object reFundPayOrder(JSONObject jsonObject) {
        return null;
    }


    @Override
    public Object findChargePayManage(JSONObject jsonObject) {
        return jdbcSession.findOne(ChargePayManage.class)
                .eq("deleted",false)
                .eq(jsonObject,"orderNo")
                .eq(jsonObject,"itemBillNo")
                .eq("status",ChargeOrderStatusEnum.ORDER_PAY_SUCCESS).exe();
    }


    /**
     * 调用现金支付
     * @return
     */
    private Object callCashPay(JSONObject jsonObject,Token token){

        String orderNo = jsonObject.getString("orderNo");

        ChargeOrderManage orderManage = jdbcSession.findOne(ChargeOrderManage.class).eq("orderNo",orderNo).exe();

        orderManage.setPayMethod(CommonEnum.COM_PAY_CASH);
        orderManage.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
        orderManage.setPaymentAmount(orderManage.getPayableAmount());
        orderManage.setPayTime(TimeUtil.timestamp());
        orderManage.setInputAmount(jsonObject.getBigDecimal("inputAmount"));
        orderManage.setChangeAmount(jsonObject.getBigDecimal("changeAmount"));
        jdbcSession.updateById(orderManage);

        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(orderNo,
                ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                "现金支付",
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(),
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(), "操作成功！", token.getUsername());

        //3、修改子订单状态
        List<ChargeOrderItem> orderItemList = jdbcSession.findArray(ChargeOrderItem.class)
                .eq("orderNo",orderNo).exe();

        for (int i = 0; i < orderItemList.size(); i++) {

            ChargeOrderItem orderItem = orderItemList.get(i);
            orderItem.setPayMethod(CommonEnum.COM_PAY_CASH);
            orderItem.setOrderNo(orderManage.getOrderNo());
            orderItem.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
            orderItem.setPaymentAmount(orderItem.getPayableAmount());
            orderItem.setPayTime(TimeUtil.timestamp());
            jdbcSession.updateById(orderItem);
        }

        //4、修改状态
        return updateData(orderManage,false,"");
    }

    /**
     * 调用临时现金支付
     * @return
     */
    private Object callInterimCashPay(JSONObject jsonObject,Token token){

        String orderNo = jsonObject.getString("orderNo");

        ChargeOrderInterim orderManage = jdbcSession.findOne(ChargeOrderInterim.class).eq("interimOrderNo",orderNo).exe();
        orderManage.setPayMethod(CommonEnum.COM_PAY_CASH);
        orderManage.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
        orderManage.setPaymentAmount(orderManage.getPayableAmount());
        orderManage.setPayTime(TimeUtil.timestamp());
        orderManage.setInputAmount(jsonObject.getBigDecimal("inputAmount"));
        orderManage.setChangeAmount(jsonObject.getBigDecimal("changeAmount"));
        jdbcSession.updateById(orderManage);

        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(orderNo,
                ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                "临时现金支付",
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(),
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(), "操作成功！", token.getUsername());

        //3、修改临时账单状态
        ChargeBillInterim interim = jdbcSession.findOne(ChargeBillInterim.class)
                .eq("interimBillNo",orderManage.getInterimBillNo())
                .noEq("billStatus",ChargeBillStatusEnum.BILL_PAID_CLOSE).exe();

        interim.setBillStatus(ChargeBillStatusEnum.BILL_PAID);
        interim.setChargeStatus(ChargeBillStatusEnum.BILL_PAID);
        jdbcSession.updateById(interim);

        //4、添加操作日志,修改支付状态
        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(interim.getInterimBillNo(),
                ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                "临时现金支付",
                ChargeBillStatusEnum.BILL_PAID.getDesc(),
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(), "操作成功！", token.getUsername());

        return Result.success();
    }

    /**
     * 微信支付入口
     * @param cpm
     * @param jsonObject
     * @return
     * @throws Exception
     */
    private Object callWeChatPay(ChargePayManage cpm, JSONObject jsonObject) throws Exception {

        String orderOrigin = cpm.getOrderOrigin().getId();
        if(Objects.isNull(orderOrigin)){
            return Result.error(123,"支付或来源有问题！");
        }

        //对应的数据
        JSONObject json = new JSONObject();
        json.put("orderOrigin",orderOrigin);
        json.put("orderNo",cpm.getOrderNo());

        // 订单临时入口和常规入口
        if(CommonEnum.COM_PAY_ROUTINE.getId().equals(orderOrigin)){

            List<ChargeOrderManage> orderManageList = jdbcSession.findArray(ChargeOrderManage.class)
                    .eq("batchOrderNo",cpm.getOrderNo()).exe();

            if(0 == orderManageList.size()){
                return Result.error(1232,"未找到支付数据！");
            }
            ChargeOrderManage orderManage = orderManageList.get(0);
            String body = "";
            if(orderManageList.size() == 1){
                body = "账单费用："+ orderManage.getBillAddress() +"-" +orderManage.getOrderYearMonth();
            }else{
                body = "账单费用："+ orderManage.getBillAddress() +"- 批量账单";
            }
            cpm.setCommunityNo(orderManage.getCommunityNo());
            jsonObject.put("body", body);
            json.put("userNo",orderManage.getUserNo());
            cpm.setAttach(json.toString());
            cpm.setOrderAmount(orderManage.getPayableAmount());
            cpm.setChargeName(orderManage.getChargeName());
            cpm.setOrderNo(orderManage.getOrderNo());
            return callRoutineWeChatPay(cpm,jsonObject);
        }else if (CommonEnum.COM_PAY_INTERIM.getId().equals(orderOrigin)){
            ChargeOrderInterim orderInterim = jdbcSession.findOne(ChargeOrderInterim.class)
                    .eq("deleted",false)
                    .eq("interimOrderNo",cpm.getOrderNo())
                    .exe();
            jsonObject.put("body", "临时收费");
            cpm.setCommunityNo(orderInterim.getCommunityNo());
            json.put("userNo",orderInterim.getUserNo());
            cpm.setAttach(json.toString());
            cpm.setOrderAmount(orderInterim.getPayableAmount());
            cpm.setChargeName(orderInterim.getChargeName());
            return callRoutineWeChatPay(cpm,jsonObject);
        }

        return Result.success();
    }

    /**
     * 调用微信支付
     * @return
     */
    private Object callRoutineWeChatPay(ChargePayManage cpm, JSONObject jsonObject) throws Exception {

        //2、调用微信支付
        JSONObject json = new JSONObject();
        json.put("subOrderNo", cpm.getId());
        json.put("spbill_create_ip", cpm.getCreateIp());
        // TODO: 2021/8/21  测试临时调整1分钱
        json.put("total_fee", cpm.getOrderAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP).toPlainString());
//         json.put("total_fee", new BigDecimal(1).toPlainString());
         json.put("openid", cpm.getOpenId());
         json.put("tradeType", cpm.getTradeType());
        json.put("body", jsonObject.getString("body"));
        json.put("attach", cpm.getAttach());
        json.put("communityNo", cpm.getCommunityNo());
        json.put("companyNo", cpm.getCompanyNo());
        json.put("notify_url", "/charge/pay/service/order/callback");
        json.put("payType",cpm.getPayMethod().getId());

        //3、调用微信支付接口
        JSONObject result = doveClient.post("/payment/wxpay/gateway/service/v2/unified/create", (http) -> {
            http.setBody(json.toJSONString());
        });
        if (result.getIntValue("code") != 200) {
            /** 编号，模块，功能，账单状态，状态，说明，操作人 */
            commonService.insetLogger(cpm.getOrderNo(),
                    ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                    "调用微信支付",
                    ChargeBillStatusEnum.BILL_UN_PAID.getDesc(),
                    ChargeOrderStatusEnum.ORDER_PAY_FAIL.getDesc(), "操作成功！", "系统自动");

            logger.error("微信支付调用失败！订单号：{}",cpm.getOrderNo());
            throw new RuntimeException("支付接口调用失败,请联系管理员");
        }

        //4、处理回调信息
        JSONObject data = result.getJSONObject("data");
        // 记录收款的商户id
        cpm.setMchId(data.getString("mchId"));
        cpm.setMchName(data.getString("mchName"));
        cpm.setSubMchId(data.getString("subMchId"));
        cpm.setSubmchName(data.getString("subMchName"));
        cpm.setPrepayId(data.getString("prepay_id"));
        cpm.setCodeUrl(data.getString("codeUrl"));
        cpm.setOrderNoThird(data.getString("platformOrderNo"));
        cpm.setPayMethod(CommonEnum.COM_PAY_WECHAT);
        cpm.setPayTime(TimeUtil.timestamp());

        jdbcSession.insert(cpm);

        return Result.success(data);
    }

    /**
     * 常规状态
     * @param orderManage
     * @return
     */
    private Object updateData(ChargeOrderManage orderManage,boolean bool,String companyNo){
        List<ChargeOrderItem> orderItemList = jdbcSession.findArray(ChargeOrderItem.class)
                .eq("orderNo",orderManage.getOrderNo()).exe();

        logger.info("支付回调处理;共修改账单：{}条！",orderItemList==null?0:orderItemList.size());

        BigDecimal amount = new BigDecimal(0);
        for (int i = 0; i < orderItemList.size(); i++) {
            ChargeOrderItem items = orderItemList.get(i);
            items.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
            items.setOptStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
            items.setUpdateName(orderManage.getCreateName());
            items.setPaymentAmount(items.getPayableAmount());
            items.setPayableAmount(BigDecimal.ZERO);
            items.setPayMethod(CommonEnum.COM_PAY_WECHAT);
            jdbcSession.updateById(items);

            // 更新类目账单
            List<ChargeBillItems> itemsList = jdbcSession.findArray(ChargeBillItems.class).eq("itemBillNo", items.getItemBillNo()).exe();
            for (ChargeBillItems each : itemsList) {
                each.setPaymentAmount(items.getPaymentAmount());
                each.setBillStatus(ChargeBillStatusEnum.BILL_PAID_FINISH);
                each.setChargeStatus(ChargeBillStatusEnum.BILL_PAID);
                each.setUpdateName(orderManage.getCreateName());
                //each.setPayableAmount(BigDecimal.ZERO);
                jdbcSession.updateById(each);
                amount = BigDecimalUtils.add(amount, items.getPaymentAmount(), 2);

                try {
                    //修改抄表状态
                    MeterReadStatist readStatists = jdbcSession.findOne(MeterReadStatist.class)
                            .eq("deleted", false)
                            .eq("houseNo", each.getHouseNo())
                            .eq("readYearMonth", each.getBillYearMonth())
                            .eq("meterTypeNo", each.getMeterTypeNo()).exe();
                    readStatists.setFeeStatus("3");
                    readStatists.setItemBillNo(each.getItemBillNo());
                    jdbcSession.updateById(readStatists);
                }catch (Exception e){
                    logger.error("修改抄表计费状态错误！",e);
                }
            }
        }

        for (int i = 0; i < orderItemList.size(); i++) {
            ChargeOrderItem items = orderItemList.get(i);

            /** 编号，模块，功能，账单状态，状态，说明，操作人 */
            commonService.insetLogger(items.getItemBillNo(),
                    ChargeLogEnum.LOG_CHARGE_BILL_CATE.getDesc(),
                    "支付操作",
                    ChargeBillStatusEnum.BILL_PAID_FINISH.getDesc(),
                    ChargeBillStatusEnum.BILL_PAID.getDesc(), "操作成功！", items.getChargeName());

            //发送消息
            if(bool){
                try{
                    // 给管家发送消息
                    // for 订单编号-->list 账单
                    // 查询账单号 是否催缴
                    if(chargeUrgingService.isRemindUrgingUser(items.getItemBillNo())) {
                        // todo 发送消息
                        JSONObject buildJson = listEmployeeByHouseNo(items.getBuildNo(), companyNo);
                        JSONArray employeeNoArray = buildJson.getJSONArray("employeeNos");
                        if (org.coraframework.util.Objects.nonEmpty(employeeNoArray)){
                            List<String> employeeNos = JSONObject.parseArray(employeeNoArray.toJSONString(), String.class);
                            if (org.coraframework.util.Objects.nonEmpty(employeeNos)) {
                                employeeNos.forEach(e -> {
                                    try {
                                        msgUniformSend(orderManage, e, TemplateType.PAY_B_TASK_SUCCESS_REMIND, null,false, companyNo);
                                    } catch (Exception e1) {
                                        logger.error("缴费任务关联账单缴费成功提醒"+e1.getMessage(), e);
                                    }
                                });
                            }
                        }
                    }
                }catch (Exception e){
                    logger.error("催缴缴费消息推送异常"+e.getMessage(), e);
                }
            }
        }

        //2、房屋状态修改
        ChargeBillHouse billHouse = jdbcSession.findOne(ChargeBillHouse.class)
                .eq("houseBillNo",orderManage.getHouseBillNo()).exe();

        // 查询房屋下的类目账单是否都支付
        List<ChargeBillItems> itemsList = jdbcSession.findArray(ChargeBillItems.class)
                .eq("houseNo", orderManage.getHouseNo())
                .eq("communityNo", orderManage.getCommunityNo())
                .eq("billYearMonth", orderManage.getOrderYearMonth())
                .eq("houseBillNo", orderManage.getHouseBillNo())
                .eq("deleted", false)
                .noEq("billStatus", ChargeBillStatusEnum.BILL_PAID_CLOSE.getId())
                .exe();
        boolean isAllPaid = true;
        for (ChargeBillItems each : itemsList) {
            if (each.getBillStatus() == ChargeBillStatusEnum.BILL_WAIT_PAID || each.getChargeStatus() == ChargeBillStatusEnum.BILL_UN_PAID) {
                isAllPaid = false;
                break;
            }
        }

        billHouse.setBillStatus(isAllPaid ? ChargeBillStatusEnum.BILL_PAID_FINISH : ChargeBillStatusEnum.BILL_WAIT_PAID);
        billHouse.setChargeStatus(isAllPaid ? ChargeBillStatusEnum.BILL_PAID : ChargeBillStatusEnum.BILL_PAID_PART);

        BigDecimal billAmountPaid = billHouse.getBillAmountPaid();
        amount = BigDecimalUtils.add(billAmountPaid, amount, 2);
        billHouse.setBillAmountPaid(amount);

        BigDecimal unpaidAmount = BigDecimalUtils.sub(billHouse.getBillAmount(), amount, 2);
        if (unpaidAmount.compareTo(BigDecimal.ZERO) < 0) {
            unpaidAmount = BigDecimal.ZERO;
        }
        billHouse.setBillAmountUnPaid(isAllPaid ? BigDecimal.ZERO : unpaidAmount);
        jdbcSession.updateById(billHouse);

        try{
            //3、小区状态修改b
            ChargeBillCommunity billCommunity = jdbcSession.findOne(ChargeBillCommunity.class)
                    .eq("communityBillNo",orderManage.getCommunityBillNo()).exe();
            billCommunity.setBillStatus(ChargeBillStatusEnum.BILL_PAID_FINISH);
            billCommunity.setChargeStatus(ChargeBillStatusEnum.BILL_PAID_PART);
            jdbcSession.updateById(billCommunity);

        }catch (Exception e){
            logger.error("支付回调处理;小区账单状态修改错误！账单："+orderManage.getCommunityBillNo(),e);
        }

        //4、添加操作日志,账单缴费成功
        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(orderManage.getHouseBillNo(),
                ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                "支付操作",
                ChargeBillStatusEnum.BILL_PAID_FINISH.getDesc(),
                ChargeBillStatusEnum.BILL_PAID.getDesc(), "操作成功！", orderManage.getChargeName());

        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(orderManage.getOrderNo(),
                ChargeLogEnum.LOG_CHARGE_ORDER_PAY.getDesc(),
                "支付操作",
                ChargeBillStatusEnum.BILL_PAID_FINISH.getDesc(),
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(), "操作成功！", orderManage.getChargeName());

        return Result.success();
    }

    /**
     * 临时状态
     * @param itemsList
     * @return
     */
    private Object updateDataInterim(ChargeOrderInterim itemsList){

        itemsList.setOrderStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
        itemsList.setOptStatus(ChargeOrderStatusEnum.ORDER_PAY_SUCCESS);
        itemsList.setPayMethod(CommonEnum.COM_PAY_WECHAT);
        itemsList.setPayTime(TimeUtil.timestamp());
        itemsList.setFinishTime(TimeUtil.timestamp());
        itemsList.setPaymentAmount(itemsList.getPayableAmount());

        jdbcSession.updateById(itemsList);

        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(itemsList.getInterimOrderNo(),
                ChargeLogEnum.LOG_CHARGE_ORDER_INT.getDesc(),
                "临时订单回调",
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(),
                ChargeOrderStatusEnum.ORDER_PAY_SUCCESS.getDesc(), "操作成功！", itemsList.getCreateName());

        //2、修改账单状态
        ChargeBillInterim billInterim = jdbcSession.findOne(ChargeBillInterim.class)
                .eq("interimBillNo",itemsList.getInterimBillNo()).exe();

        billInterim.setBillStatus(ChargeBillStatusEnum.BILL_PAID_FINISH);
        billInterim.setChargeStatus(ChargeBillStatusEnum.BILL_PAID);
        billInterim.setModifyTime(TimeUtil.timestamp());
        billInterim.setPaymentAmount(billInterim.getPayableAmount());
        jdbcSession.updateById(billInterim);

        /** 编号，模块，功能，账单状态，状态，说明，操作人 */
        commonService.insetLogger(billInterim.getInterimBillNo(),
                ChargeLogEnum.LOG_CHARGE_BILL_INT.getDesc(),
                "临时订单回调",
                ChargeBillStatusEnum.BILL_PAID_FINISH.getDesc(),
                ChargeBillStatusEnum.BILL_PAID.getDesc(), "操作成功！", billInterim.getCreateName());


        return Result.success();
    }

    private JSONObject listEmployeeByHouseNo(String houseNo, String companyNo) {
        try {
            JSONObject buildingResult = doveClient.post("/basic/building/service/get", (http) -> {
                Map<String, String> map =new HashMap<>();
                map.put("companyNo", companyNo);
                http.setHeaders(map);
                JSONObject body = new JSONObject();
                body.put("id", houseNo);
                http.setBody(body.toJSONString());
            });

            if (buildingResult.getIntValue("code")== 200) {
                JSONObject buildingJson=buildingResult.getJSONObject("data");
                if(org.coraframework.util.Objects.nonNull(buildingJson)){
                    return buildingJson;
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new JSONObject();
        }
        return new JSONObject();
    }
}
